package com.gancp.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gancp.Exception.BaseServiceException;
import com.gancp.cache.CommonCacheUtil;
import com.gancp.common.constants.Constants;
import com.gancp.common.constants.Parmeters;
import com.gancp.common.security.AESUtil;
import com.gancp.common.security.Base64Util;
import com.gancp.common.security.RSAUtil;
import com.gancp.common.util.RandomNumberCode;
import com.gancp.common.util.UUIDUtil;
import com.gancp.dao.UserInfoMapper;
import com.gancp.dao.base.IBaseMapper;
import com.gancp.entity.UserInfo;
import com.gancp.jms.IProducer;
import com.gancp.service.UserInfoService;
import com.gancp.service.base.BaseService;
import com.gancp.service.base.BaseServiceImpl;
import com.gancp.vo.UserSessionVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.catalina.User;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.bcel.Const;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.jms.Destination;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @Author gancp
 * @Date 时间被黑洞吸走了
 * @Descripition 用户信息Service实现类
 **/
@Service("userService")
@Slf4j
public class UserInfoServiceImpl extends BaseServiceImpl<UserInfo, String> implements UserInfoService {


    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private CommonCacheUtil cacheUtil;

    @Autowired
    private IProducer producer;

    @Autowired
    private Parmeters parmeters;

    @Override
    protected IBaseMapper getBaseMapper() {
        return userInfoMapper;
    }


    @Override
    public String login(String data, String key) throws Exception {
        String token = "";
        String decryptData = "";
        String platform = "";
        try {
            byte[] aesKey = RSAUtil.decryptByPrivateKey( Base64Util.decode( key ) );
            decryptData = AESUtil.decrypt( data, new String( aesKey, AESUtil.CHARSET_NAME ) );
            if (decryptData == null) {
                throw new Exception();
            }
            JSONObject jsonObject = JSON.parseObject( decryptData );
            String mobile = jsonObject.getString( "mobile" );
            String code = jsonObject.getString( "code" );
            platform = jsonObject.getString( "platform" );
            if (StringUtils.isBlank( mobile ) || StringUtils.isBlank( code )) {
                throw new Exception();
            }
            // 读取redis中的验证码
            String verifyCode = cacheUtil.getCacheValue( mobile );
            UserInfo userInfo = null;
            if (code.equals( verifyCode )) {
                userInfo = this.selectByMobile( mobile );
                // 判断用户是否存在，不存在直接注册
                if (null == userInfo) {
                    userInfo.setId( UUIDUtil.generate() );
                    userInfo.setNickname( Constants.NICK_NAME_PREFIX + mobile );
                    userInfo.setMobile( mobile );
                    userInfoMapper.insertSelective( userInfo );
                }
            } else {
                throw new BaseServiceException( "手机号码与验证码不匹配" );
            }
            // 生成token信息
            try {
                token = generateToken( userInfo );
            } catch (Exception e) {
                throw new BaseServiceException( "生成token失败" );
            }
            generateUserSession( userInfo, platform, token );
        } catch (Exception e) {
            log.error( "Fail to  decrypt data", e.getMessage() );
            if (e instanceof BaseServiceException) {
                throw new BaseServiceException( e.getMessage() );
            } else {
                throw new BaseServiceException( "数据解析失败" );
            }
        }
        return token;
    }

    @Override
    public UserInfo selectByMobile(String mobile) {
        UserInfo userInfo = null;
        List<UserInfo> list = userInfoMapper.selectByMobile( mobile );
        if (!CollectionUtils.isEmpty( list )) {
            userInfo = list.get( 0 );
        }
        return userInfo;
    }

    @Override
    public void sendVerifyCode(String phone) throws Exception {
        if (StringUtils.isBlank( phone )) {
            throw new BaseServiceException( "手机号码不能为空" );
        }
        String redisKey = Constants.PHONE_VERIFYCODE_PREFIX + phone;
        String oldVerifyCode = cacheUtil.getCacheValue( redisKey );
        if (StringUtils.isNoneEmpty( oldVerifyCode )) {
            throw new BaseServiceException( "验证码已发送，请稍后再试" );
        }
        String verifyCode = RandomNumberCode.verCode();
        // 使用消息队列处理验证码
        Destination destination = new ActiveMQQueue( parmeters.getMiaodiMsgQueueName() );
        producer.sendMessage( destination, phone + Constants.PHONE_VERIFVCODE_SPLIT + verifyCode );
        cacheUtil.cache( redisKey, verifyCode, 60 * 3 );
    }

    private String generateToken(UserInfo userInfo) {
        String sources = userInfo.getId() + "-" + userInfo.getMobile() + "-" + System.currentTimeMillis();
        return sources;
    }

    private void generateUserSession(UserInfo user, String platform, String token) {
        UserSessionVo userSessionVo = new UserSessionVo();
        userSessionVo.setUserId( user.getId() );
        userSessionVo.setMobile( user.getMobile() );
        userSessionVo.setLoginTimeStr( new SimpleDateFormat( Constants.USER_SESSION_DATE_FORMATER ).format( new Date() ) );
        userSessionVo.setPlatform( platform );
        userSessionVo.setToken( token );
        cacheUtil.putTokenWhenLogin( userSessionVo );
    }
}
